home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
BCCAPP.ARJ
/
WINDOWS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-15
|
9KB
|
463 lines
/*
*
* Windows source implementation
*
* (C) 1990 Vision Software
*
* $Id: windows.c 1.2001 91/04/25 15:07:55 pcalvin release $
*
* Comments:
*
* Used by nearly every class that performs any screen I/O. These interfaces
* will (hopefully) aid in porting any application under this system.
*
* Bugs:
*
* Not fully implemented. Right now there is no window information storage
* for re-drawing a window moved to the top.
*
* No clipping of output should the window be written to when not on top..
*
* Some torture testing should be done to determine how stable this system
* is. If we crash here, there isn't much hope for the rest of the library
*
* CODE DOCUMENTATION!!!!!!
*
*/
#include <string.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>
#include <ctype.h>
#include <stdhdr.h>
#include <adl.h>
#include "lowlevel.h"
/*
* Windows may be constructed without arguements, in that case,
* they default to the entire screen with no border.
*/
WINDOW::WINDOW(ROW r1,COL c1,ROW r2,COL c2,CO coFore,CO coBack,SZ sz,BOOL fScroll)
{
rowTop = r1;
colLeft = c1;
rowBottom = r2;
colRight = c2;
coForeground = coFore;
coBackground = coBack;
fOpen = fFalse;
szTitle = sz;
fAutomaticScroll = fScroll;
/*
* Assert the window will fit, attempts to move it if the window doesn't fit.
*/
VerifySz(FValidWindow(),"Window to large to fit on screen");
SetScrollRow(rowTop,rowBottom);
SetScrollCol(colLeft,colRight);
}
WINDOW::WINDOW(VOID)
{
rowTop = 2;
colLeft = 5;
rowBottom = 22;
colRight = 75;
coForeground = coBlack;
coBackground = coCyan;
fOpen = fFalse;
szTitle = szNil;
fAutomaticScroll = fFalse;
SetScrollRow(rowTop,rowBottom);
SetScrollCol(colLeft,colRight);
}
WINDOW::~WINDOW()
{
if (fOpen)
Close();
}
ROW WINDOW::RowQuery()
{
return (rowTop);
}
COL WINDOW::ColQuery()
{
return (colLeft);
}
VOID WINDOW::Open(VOID)
{
if (!fOpen)
{
/*
* Save screen below window.
* puchBuffer == Original screen contents
*/
puchBuffer = new UCHAR[(6+rowBottom-rowTop) * (6+colRight-colLeft) * 2];
MemoryAssert(puchBuffer);
Save(puchBuffer);
fOpen = fTrue;
}
SetRowCol(0,0);
Draw();
}
VOID WINDOW::Draw(VOID)
{
if (fOpen)
{
ClearWindow(rowTop,colLeft,rowBottom,colRight,coForeground,coBackground);
DrawBorder(rowTop-1,colLeft-1,rowBottom+1,colRight+1,bdDouble,coForeground,coBackground);
if (szTitle != szNil)
DisplayCenter(rowTop-1,(colRight+colLeft)/2,szTitle,coForeground,coBackground);
}
}
VOID WINDOW::Close(VOID)
{
if (fOpen)
{
Restore(puchBuffer);
delete puchBuffer;
fOpen = fFalse;
}
}
VOID WINDOW::Restore(PUCH puch)
{
Assert(puch != puchNil);
puttext(colLeft-1,rowTop-1,colRight+2,rowBottom+2,puch);
}
VOID WINDOW::Save(PUCH puch)
{
Assert(puch != puchNil);
gettext(colLeft-1,rowTop-1,colRight+2,rowBottom+2,puch);
}
VOID WINDOW::Move(ROW row,COL col)
{
ROW drow = rowBottom-rowTop;
COL dcol = colRight-colLeft;
Restore(puchBuffer);
rowTop = row;
colLeft = col;
rowBottom = row+drow;
colRight = col+dcol;
Save(puchBuffer);
Draw();
}
/*
* Updates the internal record of cursor position and sets position on
* the viewscreen..
*/
VOID WINDOW::SetRowCol(ROW row,COL col)
{
if (fOpen)
{
/*
* Before setting cursor, assert cursor is within screen.
*/
if (rowTop + row > rowBottom)
row = rowBottom;
if (colLeft + col > colRight)
col = colRight;
/*
* Now, set internal/external cursor
*/
rowCurrent = row;
colCurrent = col;
SetGlobalRowCol(RowAbs(row),ColAbs(col));
}
}
/*
* Clears the entire window..
*/
VOID WINDOW::Cls(VOID)
{
if (fOpen)
{
ClearWindow(rowTop,colLeft,rowBottom,colRight,coForeground,coBackground);
SetRowCol(0,0);
}
}
/*
* Clear a specific row, does not adjust cursor..
*/
VOID WINDOW::ClearRow(ROW rowClear)
{
if (fOpen)
{
ROW row = RowAbs(rowClear);
ClearWindow(row,colLeft,row,colRight,coForeground,coBackground);
}
}
/*
* Clear a specific column, also does not touch the cursor..
*/
VOID WINDOW::ClearCol(COL colClear)
{
if (fOpen)
{
COL col = ColAbs(colClear);
ClearWindow(rowTop,col,rowBottom,col,coForeground,coBackground);
}
}
/*
* String output routines..
*/
VOID WINDOW::Say(SZ sz,CO coFore,CO coBack)
{
Assert(sz != szNil);
/*
* Set up color if default arguments are used..
*/
coFore = CoFromCoCo(coFore,coForeground);
coBack = CoFromCoCo(coBack,coBackground);
if (fOpen)
{
REGISTER CHAR ch;
/*
* Draw, keep text from going outside window
*/
SetRowCol(rowCurrent,colCurrent);
CursorColor(coFore,coBack);
while ((ch = *sz++) != chNil)
{
if (ch == chReturn)
AdvanceRow();
else if (isprint(ch))
putch(ch);
AdvanceCol();
}
}
}
/*
* Sets new cursor position..
*/
VOID WINDOW::SayAt(ROW row,COL col,SZ sz,CO coFore,CO coBack)
{
SetRowCol(row,col);
Say(sz,coFore,coBack);
}
/*
* Displays a "Hot" string. The CCH'th letter is highlighted
*/
VOID WINDOW::SayHot(ROW row,COL col,SZ sz,CCH cch,CO coFore,CO coBack)
{
ROW rowDisplay = RowAbs(row);
COL colDisplay = ColAbs(col);
/*
* Normalize colours..
*/
coFore = CoFromCoCo(coFore,coForeground);
coBack = CoFromCoCo(coBack,coBackground);
HotString(rowDisplay,colDisplay,cch,sz,coFore,coBack);
}
/*
* Centers the text on the desired row
*/
VOID WINDOW::SayCentered(ROW row,SZ sz,CO coFore,CO coBack)
{
ROW rowDisplay = RowAbs(row);
COL colDisplay = ColAbs((colRight-colLeft) >> 1);
/*
* Normalize colours..
*/
coFore = CoFromCoCo(coFore,coForeground);
coBack = CoFromCoCo(coBack,coBackground);
DisplayCenter(rowDisplay,colDisplay,sz,coFore,coBack);
}
/*
* Outputs a single character at the current location..
*/
VOID WINDOW::PutCh(CHAR ch,CO coFore,CO coBack)
{
/*
* Normalize colours..
*/
coFore = CoFromCoCo(coFore,coForeground);
coBack = CoFromCoCo(coBack,coBackground);
if (fOpen)
{
SetRowCol(rowCurrent,colCurrent);
CursorColor(coFore,coBack);
if (isprint(ch))
{
putch(ch);
AdvanceCol();
}
else if (ch == chReturn)
{
AdvanceRow();
}
}
}
/*
*
* Windows internal operation
*
*/
/*
* Advances the cursor position..
*/
VOID WINDOW::AdvanceCol()
{
COL colLast = colRight - colLeft;
if (++colCurrent > colLast)
{
colCurrent = 0;
AdvanceRow();
}
SetRowCol(rowCurrent,colCurrent);
}
VOID WINDOW::AdvanceRow()
{
ROW rowLast = rowBottom - rowTop;
/*
* Be sure to before a return with the linefeed.
*/
colCurrent = 0;
/*
* The window is only scrolled up if automatic cursor
* addressing is to be observed.
*/
if (++rowCurrent > rowLast)
{
rowCurrent--;
if (fAutomaticScroll)
ScrollDrow(1);
}
SetRowCol(rowCurrent,colCurrent);
}
/*
* Allows normalizing of the colors. coDefault is used if co==coError
*/
CO WINDOW::CoFromCoCo(CO co,CO coDefault)
{
return ((co == coError) ? coDefault : co);
}
/*
* Functions to answer with the ABSOLUTE screen position. Will keep
* cursor within the window
*/
ROW WINDOW::RowAbs(ROW row)
{
ROW rowAbs = rowTop + row;
return ((rowAbs < rowBottom) ? rowAbs : rowBottom);
}
ROW WINDOW::ColAbs(COL col)
{
COL colAbs = colLeft + col;
return ((colAbs < colRight) ? colAbs : colRight);
}
VOID WINDOW::SetScrollRow(ROW rowFirst,ROW rowLast)
{
rowScrollTop = (rowFirst >= rowTop) ? rowFirst : rowTop;
rowScrollBottom = (rowLast <= rowBottom) ? rowLast : rowBottom;
}
VOID WINDOW::SetScrollCol(COL colFirst,COL colLast)
{
colScrollLeft = (colFirst >= colLeft) ? colFirst : colLeft;
colScrollRight = (colLast <= colRight) ? colLast : colRight;
}
VOID WINDOW::ScrollDrow(ROW drow)
{
if (drow > 0)
{
movetext(colScrollLeft,rowScrollTop+drow,colScrollRight,rowScrollBottom,colScrollLeft,rowScrollTop);
ClearRow(rowScrollBottom-rowTop);
}
else if (drow < 0)
{
movetext(colScrollLeft,rowScrollTop,colScrollRight,rowScrollBottom+drow,colScrollLeft,rowScrollTop-drow);
ClearRow(0);
}
}
/*
* Asserts that window is small enough to fit on the screen. Also makes sure
* the window does not travel off the screen.
* Must leave 2 columns at right edge for border + shadow
* Also, must leave 3 rows at bottom for border/shadow and help
*/
BOOL WINDOW::FValidWindow()
{
/*
* First, assert the horizontal measurements..
*/
if (colRight+2 >= colGlobalWindowRight)
{
COL dcol = 2 + colRight - colGlobalWindowRight;
colRight -= dcol;
colLeft -= dcol;
}
/*
* Now the vertical measurements..
*/
if (rowBottom+3 >= rowGlobalWindowBottom)
{
ROW drow = 3 + rowBottom - rowGlobalWindowBottom;
rowBottom -= drow;
rowTop -= drow;
}
return (fTrue);
}